package concurrent.aqs;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

// 缓冲区类
class Buffer {
    private static final int MAX_SIZE = 5;
    private Queue<Integer> queue = new ArrayBlockingQueue<>(5);
    private final Lock lock = new ReentrantLock();
    private final Condition notFull = lock.newCondition();
    private final Condition notEmpty = lock.newCondition();

    // 生产方法
    public void produce(int item) throws InterruptedException {
        lock.lock();
        try {
            // 当缓冲区满时，生产者线程等待
            while (queue.size() == MAX_SIZE) {
                System.out.println("缓冲区已满，生产者线程等待...");
                notFull.await();
            }
            // 生产数据
            queue.add(item);
            System.out.println("生产者生产了: " + item);
            // 唤醒可能正在等待的消费者线程
            notEmpty.signal();
        } finally {
            lock.unlock();
        }
    }

    // 消费方法
    public int consume() throws InterruptedException {
        lock.lock();
        try {
            // 当缓冲区为空时，消费者线程等待
            while (queue.isEmpty()) {
                System.out.println("缓冲区为空，消费者线程等待...");
                notEmpty.await();
            }
            // 消费数据
            int item = queue.poll();
            Thread.sleep(100);
            System.out.println("消费者消费了: " + item);
            // 唤醒可能正在等待的生产者线程
            notFull.signal();
            return item;
        } finally {
            lock.unlock();
        }
    }
}

// 生产者线程类
class Producer implements Runnable {
    private Buffer buffer;

    public Producer(Buffer buffer) {
        this.buffer = buffer;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            try {
                buffer.produce(i);
                Thread.sleep(100);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
}

// 消费者线程类
class Consumer implements Runnable {
    private Buffer buffer;

    public Consumer(Buffer buffer) {
        this.buffer = buffer;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            try {
                buffer.consume();
                Thread.sleep(200);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
}

// 主类
public class ConditionDemo {
    public static void main(String[] args) {
        Buffer buffer = new Buffer();
        Thread producerThread = new Thread(new Producer(buffer));
        Thread consumerThread = new Thread(new Consumer(buffer));

        producerThread.start();
        consumerThread.start();

        try {
            //producerThread.join();
            consumerThread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}